
//Copyright 1997-2009 Syrinx Development, Inc.
//This file is part of the Syrinx Web Application Framework (SWAF).
// == BEGIN LICENSE ==
//
// Licensed under the terms of any of the following licenses at your
// choice:
//
//  - GNU General Public License Version 3 or later (the "GPL")
//    http://www.gnu.org/licenses/gpl.html
//
//  - GNU Lesser General Public License Version 3 or later (the "LGPL")
//    http://www.gnu.org/licenses/lgpl.html
//
//  - Mozilla Public License Version 1.1 or later (the "MPL")
//    http://www.mozilla.org/MPL/MPL-1.1.html
//
// == END LICENSE ==
using System;
using System.Collections.Generic;
using System.Text;
using Swaf;
using System.Xml;
using Swaf.BizObj;
using Swaf.Crypto;
using System.Diagnostics;

namespace Swaf.Crypto
{
    public class X509BizObjXmlOutFormatter : IBizObjXmlOutFormatter
    {
        #region Static Variables

        private static IX509XmlCrypto s_crypto = null;
        private static object s_syncObject = new object();

        #endregion

        #region Member Variables

        private IBizObjField _bizObjFieldDef = null;
        private String _certInfoName = null;

        #endregion

        #region Constructor

        public X509BizObjXmlOutFormatter(IBizObjField bizObjFieldDef)
        {
            // Expecting an IBizObjField as the otherInfo
            _bizObjFieldDef = bizObjFieldDef;
            Debug.Assert(_bizObjFieldDef != null);

            // Expecting to find a certInfo decorator to point
            IDecorator certInfoNameDeco = _bizObjFieldDef.Decorators["cert"] as IDecorator;
            Debug.Assert(certInfoNameDeco != null);

            _certInfoName = certInfoNameDeco.Value;
            Debug.Assert(_certInfoName != null && _certInfoName != String.Empty);
        }

        #endregion

        #region Properties

        public static ICryptoManager CryptoMgr
        {
            get
            {
                // Get CryptoManager
                ICryptoManager mgr = Application.currentApp.appData["sysObjs-Crypto"] as ICryptoManager;
                if (mgr == null)
                {
                    throw new CryptoException("Unable to locate CryptoManager, ensure that the CryptographyFeature is a dependency of your application");
                }

                return mgr;
            }
        }

        public static IX509XmlCrypto Crypto
        {
            get
            {
                if (s_crypto == null)
                {
                    // Load IX509XmlCrypto object if it hasn't been loaded yet
                    lock (s_syncObject)
                    {
                        // Ensure it hasn't already been loaded by someone beating this thread to the sync object
                        if (s_crypto == null)
                        {
                            // XmlCrypto is a property of the CryptoManager
                            s_crypto = CryptoMgr.X509XmlCrypto;
                            if (s_crypto == null)
                            {
                                throw new CryptoException("CryptoManager provided does not support X509 Certification cryptography for Xml.");
                            }
                        }
                    }
                }

                return s_crypto;
            }
        }

        #endregion

        #region IBizObjXmlOutFormatter Members

        public BizObjXmlOutFormatterType FormatterType
        {
            get { return BizObjXmlOutFormatterType.Element; }
        }

        public void Format(XmlTextWriter writer, String bizObjFieldValue)
        {
            // Determine if the fields is encrypted internally, if so it must be
            // decrypted first from the internal format to the external format in the 
            // Xml serialization of the BizObj
            String clearValue = bizObjFieldValue;
            if (CryptoMgr.isValueEncrypted(bizObjFieldValue))
            {
                clearValue = CryptoMgr.decrypt(BizObjManager.BizObjCryptoKeyName, bizObjFieldValue);
            }

            // Use X509XmlCrypt to encrypt the field into the XmlTextWriter
            Crypto.Encrypt(_certInfoName, writer, _bizObjFieldDef.Name, clearValue);
        }

        #endregion
    }
}
